/****************************************************************************/
/*
* xml api for xml parse.
*/
/****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>


#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <netinet/in.h>
#include "cms_common.h"
#include "libmdm.h"
#include "cms_mdm.h"
#include "lzma/Lzma.h"
#include "cms_log.h"


/*
	Description: 
		Search i index child node
	Parameters:
		xmlShmCb: xml shm control block
		node:	the middle index child node
	return:
		return i index child node pointer
*/
objectNode_t *cmsXml_FindIndexChildi(cmsXmlCb_t *xmlShmCb, objectNode_t *node)
{
	objectNode_t *tmp = NULL;
	char *nodeName;
	int index = 0;
	
	if (node == NULL){
		return NULL;
	}
	
	nodeName = cmsXmlGetObjRealAddr(xmlShmCb, node->name);
	if(*nodeName == 'i'){
		return node;
	}
	
	index = atoi(nodeName);
	tmp = node - index;
	return tmp;
	
}

/*
	Description: 
		check object if has changed.
	Parameters:
		xmlShmCb: xml shm control block
		node:	the object node need check
	return:
		1 --  object changed
		0 -- no change
*/
int cmsXml_checkObjectChg(cmsXmlCb_t *xmlShmCb, objectNode_t *node){
	int ret = 0;
	uint16_t meta_count;
	char *meta_ptr;
	uint8_t meta_len = 0;
	cmsoffset_t attrOffset;
	uint32_t flags;
	void *object, *tmp = NULL;
	cmsoffset_t paraOffset;
	uint32_t type_size, size;

	object = cmsXmlGetObjRealAddr( xmlShmCb, xmlShmCb->offset );

	/*allocate config_size and default is 0*/
	tmp = calloc( 1, node->object_size & GET_OBJECT_SIZE_MASK );
	if (tmp == NULL){
		printf( "%s(): memory is not enough!!\n", __FUNCTION__);
		return ret;
	}
	meta_count = NTOHS(node->meta_count);
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->meta));
	while(meta_count){
		meta_len = *((uint8_t *)meta_ptr);
		if (meta_len != PADDING_META_LEN){
			/*find default parameter*/
			paraOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(cmsoffset_t)*2+sizeof(uint32_t)))));
 			attrOffset = *((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t))));
			flags = *((uint32_t *)(object + NTOHDL(attrOffset)));
			type_size = NTOHL(*((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t))));
			size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);				
			if ((flags & PARAMETER_ATTR_DEFAULTVALUE) == PARAMETER_ATTR_DEFAULTVALUE){
				/*compare default*/
				if (memcmp((object+paraOffset), (object+paraOffset+size), size) != 0){
					ret = 1;
					break;
				}
			}
			else{
				/*compare with 0*/
				if (memcmp((object+paraOffset), (tmp+paraOffset), size) != 0){
					ret = 1;
					break;
				}				
			}
			size = sizeof(uint32_t);
			if ((flags & PARAMETER_ATTR_DEFAULTATTR) == PARAMETER_ATTR_DEFAULTATTR){
				/*compare default*/				
				if (memcmp((object+attrOffset), (object+attrOffset+size), size) != 0){
					ret = 1;
					break;
				}				
			}
			else{
				/*has been modified if has other attr except FIX BITS*/
				if ((flags & ~PARAMETER_ATTR_FIX_BITS) != 0){
					ret = 1;
					break;
				}	
			}
		}
		meta_ptr = meta_ptr + meta_len;
		meta_count--;
	}

	free(tmp);

	printf( "%s(): Parameter change check ret:%d!!\n", __FUNCTION__, ret);
	return ret;
}

/*
	Description: 
		Search and get an empty index child node
	Parameters:
		xmlShmCb:	xml shm control block
		node:	the middle index child node
	return:
		return index child node or NULL if all index child node is occupied
*/
objectNode_t *cmsXml_getIndexChild(cmsXmlCb_t *xmlShmCb, objectNode_t *node)
{
	objectNode_t *next, *current = NULL;
	char *ptr;
	int count;
	int i = 1;
	
	if (node == NULL){
		return NULL;
	}

	count = node->sibling.child_count;
	while (count > 0){
		next = node + i;
		if ((next->attributes & ATTR_NODECONFIGURED) != ATTR_NODECONFIGURED){
			current = next;
			break;
		}
		i++;
		count--;
	}			
	
	if (current){
		ptr = cmsXmlGetObjRealAddr(xmlShmCb, current->name);
		xmlShmCb->objectIndex = atoi(ptr);	
		return current;
	}
	return NULL;
}

/*
	Description: 
		use to get parameter name
	Parameters:
		xmlShmCb:	xml shm control block
		node: the node pointer
		index: parameter index number
	return:
		return pointer of name
		
*/
char *cmsXml_getParameterNamePtr(cmsXmlCb_t *xmlShmCb, objectNode_t *node, int index){
	void *meta_ptr;
	char *ptr = NULL;
	uint8_t meta_len = 0;

	if (index > node->meta_count)
		return NULL;

	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, node->meta);	

	while(index > 0){
		/*get meta ptr*/
		meta_len = *((uint8_t *)meta_ptr);

		ptr = meta_ptr + sizeof(uint8_t);


		meta_ptr = meta_ptr + meta_len;

		index--;
	}
	if (meta_len == PADDING_META_LEN){
		return NULL;	/*it's padding meta*/
	}

	return ptr;
}

int
strlenicmp(
    char *str1,
    char *str2, 
    uint32_t *namelen
)
{
    char ch1, ch2;
    int diff;
	int len = 0;
 
    if ( str1 == str2 ) {
        return 0;
    } else if ( str1 == NULL ) {
        return -1;
    } else if ( str2 == NULL ) {
        return 1;
    }

 	while ((*str2 == '0')||(*str2 == ' ')){
		len++;
		str2++;
	}
    while ( 1 ) {
        diff = (ch1 = *str1) - (ch2 = *str2);
        if ( diff < 0 ) {
            if ( (diff != ('A'-'a')) || (ch1 < 'A') || (ch1 > 'Z')) { 
                /* found difference */
				if ((ch1 == '\0') && (ch2 == '.')){
					/*found difference, but two strings are the same*/
					if (namelen != NULL){
						*namelen = len;
					}					
					break;
				}			
                return -1;
            } 
            /* else matched with different letter case -> continue */
        } else if ( diff > 0 ) {
            if ( (diff != ('a'-'A')) || (ch1 < 'a') || (ch1 > 'z') ) {
                /* found difference */
                return 1;
            }
            /* else matched with different letter case -> continue */
        } else if (( ch1 == '\0' )) {
            /* end of str1 && end of str2 */
			/*should happen at last string!*/
			if (namelen != NULL){
				*namelen = len;
				*namelen |= LAST_NAME_FOUND;
			}				
            break;
        } 
        /* else matched exactly -> continue */
		len++;
        str1++;
        str2++;
    }


    return 0;
} 


/*
	Description: 
		Search object node
	Parameters:
		xmlShmCb:	xml shm control block
		node:	object node's middle
		name:	the child node's name
		namelen: use to get the child node's name length
	return:
		return the object node's ptr or NULL
*/
objectNode_t *cmsXml_SearchChildNode( cmsXmlCb_t *xmlShmCb, objectNode_t *node, char *name, uint32_t *namelen)
{
#ifdef XML_TEST_DEBUG
	printf( "[%s-%d], Entrance.\n", __FUNCTION__, __LINE__);
#endif
	int retcode;
	objectNode_t *current;
	char *namePtr;
	int count = 0, i = 0;
	
	if (node == NULL){
		return NULL;
	}
	current = node;

	/*check index child first, if the node is index child, don't use AVL tree search*/
	if ((NTOHL(node->attributes) & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
		count = NTOHL(node->sibling.child_count);
		while (count >= 0){
			current = node + i;
			namePtr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(current->name));
			if (strlenicmp(namePtr, name, namelen) == 0){
				return current;
			}
			i++;
			count--;
		}
		return NULL;		
	}

	/*AVL tree search*/
	while(current){
		namePtr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(current->name));

		retcode = strlenicmp(namePtr, name, namelen);
		if (retcode == 0){
#ifdef XML_TEST_DEBUG
			printf( "[%s-%d], Exit.\n", __FUNCTION__, __LINE__);
#endif
			return current;
		}
		else if (retcode > 0){
			current = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(current->sibling.tree.next));	/*smaller*/
		}
		else{
			current = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(current->sibling.tree.prev));	/*larger*/
		}
	}
	return NULL;
}

int cmsXml_SearchParameter(cmsXmlCb_t *xmlShmCb, objectNode_t	*node, char *parameter, char **meta){
	uint16_t meta_count;
	char *meta_ptr;
	uint8_t meta_len = 0;

#ifdef XML_TEST_DEBUG
	printf( "[%s-%d], parameter: %s Entrance.\n", __FUNCTION__, __LINE__, parameter);
#endif
	meta_count = NTOHS(node->meta_count);
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->meta));
	while(meta_count){
		meta_len = *((uint8_t *)meta_ptr);
		if ((meta_len != PADDING_META_LEN)&&!strcmp(parameter, (meta_ptr+sizeof(uint8_t)))){
			/*find*/
			*meta = meta_ptr;
#ifdef XML_TEST_DEBUG
			printf( "[%s-%d]: parameter %s leave CMS_OK\n", __FUNCTION__, __LINE__, parameter);
#endif
			return CMS_OK;
		}
		meta_ptr = meta_ptr + meta_len;
		meta_count--;
	}
	
#ifdef XML_TEST_DEBUG
	printf( "[%s-%d], parameter: %s Exit NOK.\n", __FUNCTION__, __LINE__, parameter);
#endif
	return CMS_NOK;
}


static int cmsXml_CheckChildStatus( cmsXmlCb_t *xmlShmCb, objectNode_t *node )
{
	int ret = 0;

	if ((node->attributes & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
		/* just return configured if this node is indexchild. */
		return 1;
	}
	else{
			
		if (((node->attributes & ATTR_NODECONFIGURED) == ATTR_NODECONFIGURED)&&((node->attributes & ATTR_ALWAYSACTIVE) != ATTR_ALWAYSACTIVE)){
			ret = 1;
			return ret;
		}

		if(node->sibling.tree.prev){
			if ((ret = cmsXml_CheckChildStatus(xmlShmCb, cmsXmlGetObjRealAddr(xmlShmCb, node->sibling.tree.prev))) == 1){
				return ret;
			}
		}
		if(node->sibling.tree.next){
			if ((ret = cmsXml_CheckChildStatus(xmlShmCb, cmsXmlGetObjRealAddr(xmlShmCb, node->sibling.tree.next))) == 1){
				return ret;
			}
		}
	}
	return ret;
}

/*
	Description: 
		use to active/deactive index object node
	Parameters:
		xmlShmCb:	xml shm control block
		objOff: the object offset
		active: active type
				#define INDEX_OBJECT_ACTIVE		1
				#define INDEX_OBJECT_DEACTIVE	0
	return:
		return CMS_OK
	call by:

*/
int cmsXml_setNodeStatus( cmsXmlCb_t *xmlShmCb, objectNode_t *node, int active )
{
	objectNode_t *parent = NULL, *child = NULL;
	int flag = 0;
#if 0
	objectNode_t *inode = NULL;
	int count = 0, i = 1, childCount = 0;
	char *name = NULL;
#endif

	if (active == 1){	/*enable, called at cmsXml_SetIndexObject or cmsXmlSetParameter*/
#if !defined(SYSDEF_PARSER_ON_HOST)
		if ( xmlShmCb->IA )
		{
			/* set attribute to preobj. */
			cmsXml_SetPreObjStatus( xmlShmCb, xmlShmCb->offset, INDEX_OBJECT_ACTIVE );
		}
#endif
		parent = node;
		while (parent){
			parent->attributes |= ATTR_NODECONFIGURED;
			/*if node is index child, remove ATTR_NODECONFIGURED from i node*/
#if 0
			/* prototype nodes are always configured for now. */
			if ((parent->attributes & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
				name = cmsXmlGetObjRealAddr(xmlShmCb, parent->name);
				count = atoi(name);
				inode = parent - count;
#ifdef CMS_XML_PARSE_PHASE_1
				// for store data to "i" node in config.xml. To have ATTR_NODECONFIGURED for stroe "i" node in config.xml.
				if ( !(inode->attributes & ATTR_FILTERMATCHNODE) ) inode->attributes &= ~ATTR_NODECONFIGURED;
#else
				inode->attributes &= ~ATTR_NODECONFIGURED;
#endif
			}
#endif
			parent = cmsXmlGetObjRealAddr(xmlShmCb, parent->parent);
		}
	}else{	/*disable*/
		/*check child's status*/

		/*if original's attr is NODECONFIGURED, check child's status*/
//		child = cmsXmlGetObjRealAddr(xmlShmCb, node->child);
		if ((node->attributes & ATTR_NODECONFIGURED) == ATTR_NODECONFIGURED){
			/*if one of the child is NODECONFIGURED, keep node's attr to NODECONFIGURED*/
//			flag = cmsXml_CheckChildStatus(xmlShmCb, child);
			/*otherwise, remove NODECONFIGURED from node's attr*/
//			if (flag == 0){
//				node->attributes &= ~ATTR_NODECONFIGURED;
				/*check parent's attr need to modify or not*/
//				parent = cmsXmlGetObjRealAddr(xmlShmCb, node->parent);
#if !defined(SYSDEF_PARSER_ON_HOST)
				if ( xmlShmCb->IA )
				{
					/* set attribute to preobj. */
					cmsXml_SetPreObjStatus( xmlShmCb, xmlShmCb->offset, INDEX_OBJECT_INACTIVE );
				}
#endif
				parent = node;
				while (parent){
					child = cmsXmlGetObjRealAddr(xmlShmCb, parent->child);
					if (child != NULL){
						flag = cmsXml_CheckChildStatus(xmlShmCb, child);
						if ((flag == 0)&&((parent->attributes & ATTR_OBJECTNODE) == ATTR_OBJECTNODE)){
							/*if the node is object node, check the own parameters are changed or not*/
#if !defined(SYSDEF_PARSER_ON_HOST)
							if ( xmlShmCb->IA )
							{
								flag = 1;
							}
							else
#endif
							flag = cmsXml_checkObjectChg(xmlShmCb, parent);
						}
					}
					else{
						flag = 0;
					}
					if ((flag == 0)&&((parent->attributes & ATTR_ALWAYSACTIVE) != ATTR_ALWAYSACTIVE)){
						parent->attributes &= ~ATTR_NODECONFIGURED;
					}
#if 0
					if ((parent->attributes & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){		
						childCount = parent->sibling.child_count;
						name = cmsXmlGetObjRealAddr(xmlShmCb, parent->name);
						if (*name != 'i'){
							count = atoi(name);			
							inode = parent - count;
							while (childCount > 0){
								child = inode + i;
								if ((child->attributes & ATTR_NODECONFIGURED) == ATTR_NODECONFIGURED){
									break;
								}
								i++;
								childCount--;
							}
							if (childCount == 0){
								inode->attributes |= ATTR_NODECONFIGURED;
							}
						}
					}
#endif
					parent = cmsXmlGetObjRealAddr(xmlShmCb, parent->parent);
				}				
//			}
			
		}
		/*otherwise, don't care*/
	}
	
	return CMS_OK;
}

/*
	Description: 
		use to copy object value from node to node, including descendants
	Parameters:
		xmlShmCb:	xml shm control block
		src: src node
		dst: dst node
		flag: use to distinguish copy node to node or reset value from i node to other node
				#define COPY_OBJECT_VALUE		1
				#define RESET_INDEXCHILD_OBJECT_VALUE	0
	return:
		return CMS_OK
	call by:

*/
int cmsXml_copyObjectNodeToNode(cmsXmlCb_t *xmlShmCb, objectNode_t *src, objectNode_t *dst, int flag){
	void *object, *sobject;
	char *metaAddr, *meta_ptr, *name;
	cmsoffset_t metaOffset, paraOffset, attrOffset;
	uint16_t meta_count;
	uint8_t meta_len = 0;
	uint32_t type_size = 0;
	uint32_t attr = 0, child_count = 0, i;
	int size = 0;
	objectNode_t *snext, *dnext, *sprev, *dprev, *schild, *dchild;

#ifdef XML_TEST_DEBUG
	printf( "[%s-%d], Entrance.\n", __FUNCTION__, __LINE__);
#endif
	if (dst->object_size == 0)
		goto check_child;

	sobject = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(src->object));
	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(dst->object));
	meta_count = NTOHS(dst->meta_count);
	//memcpy(object, sobject, node->object_size);
	memcpy(object, sobject, NTOHL(dst->config_size));
	metaAddr = sobject -sizeof(cmsoffset_t);
	metaOffset = *((cmsoffset_t *)metaAddr);
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));

	if (flag == RESET_INDEXCHILD_OBJECT_VALUE){
		if ((dst->attributes & ATTR_ALWAYSACTIVE) != ATTR_ALWAYSACTIVE){
			dst->attributes &= ~ATTR_NODECONFIGURED;
		}
	}
	else if (flag == COPY_OBJECT_VALUE){
		dst->attributes = src->attributes;
	}
	while(meta_count)
	{
		meta_len = *((uint8_t *)meta_ptr);
		if (meta_len != PADDING_META_LEN){
			type_size = NTOHL(*((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t))));
			paraOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(cmsoffset_t)*2+sizeof(uint32_t)))));
			attrOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(cmsoffset_t)*1+sizeof(uint32_t)))));
			attr = NTOHL(*((uint32_t *)(sobject+attrOffset)));
			if ((attr & PARAMETER_ATTR_CONFIG) != PARAMETER_ATTR_CONFIG){//Ex:interface name don't want user to modify, so its' value will be non-configure and read-only
					if ((attr & PARAMETER_ATTR_READONLY) != PARAMETER_ATTR_READONLY){
						size = (int)(type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS));
						memcpy((object+paraOffset), (sobject+paraOffset), size);
					}
			}
		}
		meta_ptr = meta_ptr + meta_len;
		meta_count--;
	}
check_child:	
	attr = NTOHL(dst->attributes);
	if ((attr & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
		name = cmsXmlGetObjRealAddr(xmlShmCb, NTOHL(dst->name));
		if (!strcmp(name, "i")){
			child_count = NTOHL(dst->sibling.child_count);
			i = 1;
			while (child_count > 0){
				cmsXml_copyObjectNodeToNode(xmlShmCb, src+i, dst+i, flag);
				child_count--;
				i++;
			}
		}
	}
	else{
		if (dst->sibling.tree.prev){
			dprev = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(dst->sibling.tree.prev));
			sprev = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(src->sibling.tree.prev));
			cmsXml_copyObjectNodeToNode(xmlShmCb, sprev, dprev, flag);
		}
		if (dst->sibling.tree.next){
			dnext = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(dst->sibling.tree.next));
			snext = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(src->sibling.tree.next));
			cmsXml_copyObjectNodeToNode(xmlShmCb, snext, dnext, flag);
		}		
	}
	
	if (dst->child){
		dchild = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(dst->child));
		schild = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(src->child));		
		cmsXml_copyObjectNodeToNode(xmlShmCb, schild, dchild, flag);
	}

	return 0;
}

/*return array of (name, type, value)*/
/*
	Description: 
		use to get default parameter
	Parameters:
		xmlShmCb:	xml shm control block
		objOff: the object offset
		parameter:	pointer array of p1, p2, p3,....
		count: parameter number
	return:
		return pointer array of (name, value, type_size)
	example:
	{
		parameterValue_t *value;
		char *get[] = {"Name", "Version", "Date", "Description"};
		value = cmsXmlGetParameter(xmlShmCb, object, count, get);
	}
*/
parameterValue_t *cmsXml_getDefaultParameter(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, int count, char **parameter){
	cmsoffset_t metaOffset, nodeOffset, objectOffset, attrOffset;
	char *metaAddr, *nodeAddr;
	parameterValue_t *ptr, *value;
	objectNode_t	*node, *parent, *middle;
	uint16_t meta_count;
	void *meta_ptr, *object, *sobject;
	uint8_t meta_len = 0;
	char **pp;
	uint32_t type = 0;
	uint32_t flags;

#ifdef XML_TEST_DEBUG
	printf( "[%s-%d], Entrance.\n", __FUNCTION__, __LINE__);
#endif
	if(parameter == NULL) {
		printf( "%s(): Error!! parameter is nil\n", __FUNCTION__);
		return NULL;
	}

	object = cmsXmlGetObjRealAddr(xmlShmCb, objOff);

	/*use object to find the object node*/
	nodeAddr = object -sizeof(cmsoffset_t)*2;
	nodeOffset = *((cmsoffset_t *)nodeAddr);
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));
	
	ptr = malloc(sizeof(parameterValue_t)*count);
	value = (parameterValue_t *)ptr;
	memset(value, 0, sizeof(parameterValue_t)*count);
	pp = parameter;
	while(count > 0){
		/*use object to find the meta data*/
		metaAddr = object -sizeof(cmsoffset_t);
//		memcpy(&metaOffset, metaAddr, sizeof(cmsoffset_t));
		metaOffset = *((cmsoffset_t *)metaAddr);
		/*get meta ptr*/
		meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, metaOffset);	

		/*use object to find the object node*/
		nodeAddr = object -sizeof(cmsoffset_t)*2;
//		memcpy(&nodeOffset, nodeAddr, sizeof(cmsoffset_t));
		nodeOffset = *((cmsoffset_t *)nodeAddr);
		node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, nodeOffset);

		meta_count = node->meta_count;

		if(*pp != NULL){
			while(meta_count){

	//			memcpy(&meta_len, meta_ptr, sizeof(uint8_t));
				meta_len = *((uint8_t *)meta_ptr);
				/*compare meta name*/
				if ((meta_len != PADDING_META_LEN)&&!strcmp(*pp, (meta_ptr+sizeof(uint8_t)))){	/*find meta*/		
					//name_len = strlen(meta_ptr+sizeof(uint8_t)) + 1;	/*1 for \0*/
					value->name = *pp; //malloc(name_len);
					value->type_size = *((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t)));

					type = value->type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);

					/*-(type_size + attribute offset + meta parameter offset)*/
					objectOffset = *((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t) + sizeof(cmsoffset_t)*2)));
					if ((node->attributes & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
						/*index child node's default value at i node*/
						parent = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->parent));
						middle = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(parent->child));
						sobject = cmsXmlGetObjRealAddr(xmlShmCb, middle->object);
						value->value = sobject + objectOffset;
					}
					else{
						attrOffset = *((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t))));
						flags = *((uint32_t *)(object + NTOHDL(attrOffset)));
						if ((flags & PARAMETER_ATTR_DEFAULTVALUE) == PARAMETER_ATTR_DEFAULTVALUE){
							value->value = (object + objectOffset+type);
						}
						else{
							printf( "%s(): Warning!! Name = %p doesn't have default value.\n", __FUNCTION__, *pp);
						}
					}


					break;
				}
				meta_ptr = meta_ptr + meta_len;
				meta_count--;
				
			}
		}else{
			printf( "%s(): Warning!! Name = %p.\n", __FUNCTION__, *pp);
		}
		if(meta_count == 0){
			free(ptr);
			printf( "%s: cannot find parameter, %s\n", __FUNCTION__, *pp);
			return NULL;
		}
		count--;
		pp++;	
		value++;
	}
	return ptr;
}

/*
	Description: 
		use to get parameter attribute
	Parameters:
		xmlShmCb:	xml shm control block
		objOff: the object offset
		parameter:	parameter name
	return:
		return attribute flags
	example:
	{
		uint32_t *parameter;
		*p2 = "Version"
		parameter = (uint32_t *)p2;
		attr = cmsXmlGetParameterAttr(xmlShmCb, object, (char *)parameter);
	}
*/
uint32_t cmsXml_getDefaultParameterAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter){
	cmsoffset_t metaOffset, nodeOffset, attrOffset;
	char *metaAddr, *nodeAddr;
	static uint32_t defaultFlags;
	objectNode_t	*node;
	uint16_t meta_count;
	void *meta_ptr, *object;
	uint8_t meta_len = 0;

	if(parameter == NULL) {
		printf( "%s(): Error!! parameter is nil\n", __FUNCTION__);
		return CMS_NOK;
	}

	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(objOff));
	/*use object to find the meta data*/
	metaAddr = object -sizeof(cmsoffset_t);
//	memcpy(&metaOffset, metaAddr, sizeof(cmsoffset_t));
	metaOffset = *((cmsoffset_t *)metaAddr);

	/*use object to find the object node*/
	nodeAddr = object -sizeof(cmsoffset_t)*2;
//	memcpy(&nodeOffset, nodeAddr, sizeof(cmsoffset_t));
	nodeOffset = *((cmsoffset_t *)nodeAddr);
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));

	meta_count = node->meta_count;
	/*get meta ptr*/
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));	
		
	while(NTOHS(meta_count)){
//		memcpy(&meta_len, meta_ptr, sizeof(uint8_t));
		meta_len = *((uint8_t *)meta_ptr);
		if ((meta_len != PADDING_META_LEN)&&!strcmp(parameter, (meta_ptr+sizeof(uint8_t)))){	/*find meta, change the value*/
//			memcpy(&attrOffset, (meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t))), sizeof(cmsoffset_t));
			attrOffset = *((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t))));
//			attr_ptr = cmsXmlGetObjRealAddr(xmlShmCb, attrOffset);
//			memcpy(&flags, attr_ptr, sizeof(uint32_t));
			defaultFlags = *((uint32_t *)(object + NTOHDL(attrOffset)));
			if ((defaultFlags & PARAMETER_ATTR_DEFAULTATTR) == PARAMETER_ATTR_DEFAULTATTR){
				defaultFlags = *((uint32_t *)(object + NTOHDL(attrOffset)+sizeof(uint32_t)));
			}
			else{
				defaultFlags = 0;
			}
			break;
		}
		meta_ptr = meta_ptr + meta_len;
		meta_count--;
	}	
	return defaultFlags;
}

/*
	Description: 
		use to get parameter extend attribute
	Parameters:
		xmlShmCb:	xml shm control block
		objOff: the object offset
		parameter:	parameter name
	return:
		return attribute extend flags
	example:
	{
		uint32_t *parameter;
		*p2 = "Version"
		parameter = (uint32_t *)p2;
		attr = cmsXmlGetParameterExtAttr(xmlShmCb, object, (char *)parameter);
	}
*/
uint16_t cmsXml_getDefaultParameterExtAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter){
	uint32_t flags;
	static uint16_t attr;

	if(parameter == NULL) {
		printf( "%s(): Error!! parameter is nil\n", __FUNCTION__);
		return 0;
	}
	
	flags = cmsXml_getDefaultParameterAttr(xmlShmCb, objOff, parameter);
	attr = flags >> 16;
	
	return attr;
}

cmsoffset_t cmsXmlGetPtrOffset(cmsXmlCb_t *xmlShmCb, void *ptr){
	cmsoffset_t offset;
	
	offset = (cmsoffset_t)ptr-(cmsoffset_t)xmlShmCb->baseaddr;

	return offset;
}


/*
	Description: 
		use to get parameter attribute
	Parameters:
		xmlShmCb:	xml shm control block
		objOff: the object offset
		parameter:	parameter name
	return:
		return attribute flags
	example:
	{
		uint32_t *parameter;
		*p2 = "Version"
		parameter = (uint32_t *)p2;
		attr = cmsXmlGetParameterAttr(xmlShmCb, object, (char *)parameter);
	}
*/
uint32_t cmsXml_getParameterAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter){
	cmsoffset_t metaOffset, nodeOffset, attrOffset;
	char *metaAddr, *nodeAddr;
	static uint32_t flags;
	objectNode_t	*node;
	uint16_t meta_count;
	void *meta_ptr, *object;
	uint8_t meta_len = 0;

	if(parameter == NULL) {
		printf( "%s(): Error!! parameter is nil\n", __FUNCTION__);
		return CMS_NOK;
	}

	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(objOff));
	/*use object to find the meta data*/
	metaAddr = object -sizeof(cmsoffset_t);
//	memcpy(&metaOffset, metaAddr, sizeof(cmsoffset_t));
	metaOffset = *((cmsoffset_t *)metaAddr);

	/*use object to find the object node*/
	nodeAddr = object -sizeof(cmsoffset_t)*2;
//	memcpy(&nodeOffset, nodeAddr, sizeof(cmsoffset_t));
	nodeOffset = *((cmsoffset_t *)nodeAddr);
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));

	meta_count = node->meta_count;
	/*get meta ptr*/
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));	
		
	while(NTOHS(meta_count)){
//		memcpy(&meta_len, meta_ptr, sizeof(uint8_t));
		meta_len = *((uint8_t *)meta_ptr);
		if ((meta_len != PADDING_META_LEN)&&!strcmp(parameter, (meta_ptr+sizeof(uint8_t)))){	/*find meta, change the value*/
//			memcpy(&attrOffset, (meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t))), sizeof(cmsoffset_t));
			attrOffset = *((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t))));
//			attr_ptr = cmsXmlGetObjRealAddr(xmlShmCb, attrOffset);
//			memcpy(&flags, attr_ptr, sizeof(uint32_t));
			flags = *((uint32_t *)(object + NTOHDL(attrOffset)));
			break;
		}
		meta_ptr = meta_ptr + meta_len;
		meta_count--;
	}	
	return flags;
}

/*return array of (name, type, value)*/
/*
	Description: 
		use to get parameter
	Parameters:
		xmlShmCb:	xml shm control block
		objOff: the object offset
		parameter:	pointer array of p1, p2, p3,....
		count: parameter number
	return:
		return pointer array of (name, value, type_size)
	example:
	{
		parameterValue_t *value;
		char *get[] = {"Name", "Version", "Date", "Description"};
		value = cmsXmlGetParameter(xmlShmCb, object, count, get);
	}
*/
parameterValue_t *cmsXml_getParameter(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, int count, char **parameter){
	cmsoffset_t metaOffset, nodeOffset, objectOffset;
	char *metaAddr, *nodeAddr;
	parameterValue_t *ptr, *value;
	objectNode_t	*node;
	uint16_t meta_count;
	void *meta_ptr, *object;
	uint8_t meta_len = 0;
	char **pp;
	uint32_t type = 0;

#ifdef XML_TEST_DEBUG
	printf( "[%s-%d], Entrance.\n", __FUNCTION__, __LINE__);
#endif
	if(parameter == NULL) {
		printf( "%s(): Error!! parameter is nil\n", __FUNCTION__);
		return NULL;
	}

	object = cmsXmlGetObjRealAddr(xmlShmCb, objOff);
	ptr = malloc(sizeof(parameterValue_t)*count);
	value = (parameterValue_t *)ptr;
	memset(value, 0, sizeof(parameterValue_t)*count);
	pp = parameter;
	while(count > 0){
		/*use object to find the meta data*/
		metaAddr = object -sizeof(cmsoffset_t);
//		memcpy(&metaOffset, metaAddr, sizeof(cmsoffset_t));
		metaOffset = *((cmsoffset_t *)metaAddr);
		/*get meta ptr*/
		meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, metaOffset);	

		/*use object to find the object node*/
		nodeAddr = object -sizeof(cmsoffset_t)*2;
//		memcpy(&nodeOffset, nodeAddr, sizeof(cmsoffset_t));
		nodeOffset = *((cmsoffset_t *)nodeAddr);
		node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, nodeOffset);

		meta_count = node->meta_count;

		if(*pp != NULL){
			while(meta_count){

	//			memcpy(&meta_len, meta_ptr, sizeof(uint8_t));
				meta_len = *((uint8_t *)meta_ptr);
				/*compare meta name*/
				if ((meta_len != PADDING_META_LEN)&&!strcmp(*pp, (meta_ptr+sizeof(uint8_t)))){	/*find meta*/		
					//name_len = strlen(meta_ptr+sizeof(uint8_t)) + 1;	/*1 for \0*/
					value->name = *pp; //malloc(name_len);
					//strcpy(value->name, (meta_ptr+sizeof(uint8_t)));
	//				memcpy(&value->type_size, (meta_ptr + meta_len - sizeof(uint32_t)), sizeof(uint32_t));
	//				memcpy(&type_size, (meta_ptr + meta_len - sizeof(uint32_t)), sizeof(uint32_t));
					value->type_size = *((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t)));
					if ((value->type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
						type = PARAMETER_TYPE_STRING;
					}
					else{
						type = value->type_size;
					}
					switch (type){
					case PARAMETER_TYPE_UINT8:
					case PARAMETER_TYPE_BOOLEAN:
						value->max.unsign.u8 = *((uint8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.unsign.u8 = *((uint8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						break;
					case PARAMETER_TYPE_UINT16:
						value->max.unsign.u16 = *((uint16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.unsign.u16 = *((uint16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						break;
					case PARAMETER_TYPE_UINT32:
						value->max.unsign.u32 = *((uint32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.unsign.u32 = *((uint32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));				
						break;
					case PARAMETER_TYPE_UINT64:
						value->max.unsign.u64 = *((uint64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.unsign.u64 = *((uint64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));			
						break;
					case PARAMETER_TYPE_SINT7:
						value->max.sign.s7 = *((int8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.sign.s7 = *((int8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));				
						break;
					case PARAMETER_TYPE_SINT15:
						value->max.sign.s15 = *((int16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.sign.s15 = *((int16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));			
						break;
					case PARAMETER_TYPE_SINT31:
						value->max.sign.s31 = *((int32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.sign.s31 = *((int32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));				
						break;
					case PARAMETER_TYPE_SINT63:
						value->max.sign.s63 = *((int64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.sign.s63 = *((int64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));			
						break;
					}
	//				value->max = *((uint32_t *)(meta_ptr + meta_len - (sizeof(uint32_t)*3 + sizeof(cmsoffset_t)*2)));
	//				value->min = *((uint32_t *)(meta_ptr + meta_len - (sizeof(uint32_t)*2 + sizeof(cmsoffset_t)*2)));

	//				value->type_size = type_size;

	//				value->value = malloc(size);
					/*-(type_size + attribute offset + meta parameter offset)*/
					objectOffset = *((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t) + sizeof(cmsoffset_t)*2)));
					value->value = (object + objectOffset);
#if 0	/*because ram to rom also call getParameter, cannot use this way*/
					if ((value->type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
					/*if the type_size is string, get the real string size*/
						value->type_size = strlen(value->value) + PARAMETER_TYPE_STRING;
					}
#endif				
	//				memcpy(value->value, (object + objectOffset), size);

					break;
				}
				meta_ptr = meta_ptr + meta_len;
				meta_count--;
				
			}
		}else{
			printf( "%s(): Warning!! Name = %p.\n", __FUNCTION__, *pp);
		}
		if(meta_count == 0){
			free(ptr);
			printf( "%s: cannot find parameter, %s\n", __FUNCTION__, *pp);
			return NULL;
		}
		count--;
		pp++;	
		value++;
	}
	return ptr;
}

/*
	Description: 
		use to get parameter extend attribute
	Parameters:
		xmlShmCb:	xml shm control block
		objOff: the object offset
		parameter:	parameter name
	return:
		return attribute extend flags
	example:
	{
		uint32_t *parameter;
		*p2 = "Version"
		parameter = (uint32_t *)p2;
		attr = cmsXmlGetParameterAttr(xmlShmCb, object, (char *)parameter);
	}
*/

uint16_t cms_getParameterExtAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter){
	uint32_t flags;
	static uint16_t attr;

#ifdef XML_TEST_DEBUG
	printf( "[%s-%d], Entrance.\n", __FUNCTION__, __LINE__);
#endif
	if(parameter == NULL) {
		printf( "%s(): Error!! parameter is nil\n", __FUNCTION__);
		return 0;
	}
	
	flags = cmsXml_getParameterAttr(xmlShmCb, objOff, parameter);
	attr = flags >> 16;

#ifdef XML_TEST_DEBUG
	printf( "[%s-%d], Exit.\n", __FUNCTION__, __LINE__);
#endif
	return attr;
}

/*
	Description: 
		The API used to store xml data module from memory to cms file.
	Parameters:
		xmlShmCb - xml share memory control block.
		xmlPath  - xml file for sem keys.
		cmsPath  - cms file path name.
	return:
		CMS_NOK  - fail.
		CMS_OK   - success.
	call by:
		xmlToShm.c main().
*/
int cms_genCmsFile(cmsXmlCb_t *xmlShmCb, char *xmlPath, char *cmsPath){
	key_t keys;
	int semid = 0;
	struct sembuf sbEnter[2] = { {0, 0, 0}, {0, 1, SEM_UNDO} };
	struct sembuf sbLeave = {0, -1, SEM_UNDO};  /* set to allocate resource */
	FILE *fp = NULL;
	SRes ret = 0;
	
	/*create sem*/
	if(xmlPath != NULL){ 
		keys=ftok(xmlPath, 'a');
		semid = semget(keys, 1, 0666);
		if (semid == -1){
			printf( "%s(): semget fail.\n", __FUNCTION__);
			return CMS_NOK;
		}
		if (semop(semid, &sbEnter[0], sizeof(sbEnter)/sizeof(struct sembuf)) == -1) {
			printf( "%s(): semop fail\n", __FUNCTION__);
			return CMS_NOK;
		}
	}

	/*check cms file is exist*/
	if(access(cmsPath, F_OK)!=0){
		printf( "[%s-%d]: cms file not exist, create cms file.\n", __FUNCTION__, __LINE__);
		fp = fopen(cmsPath,"a+"); 
		if(fp==NULL){
			if ((xmlPath != NULL)&&(semop(semid, &sbLeave, sizeof(sbLeave)/sizeof(struct sembuf)) == -1)) {
				printf( "%s(): semop fail\n", __FUNCTION__);
				return CMS_NOK;
			}			
			return CMS_NOK;
		}
		fclose(fp);
	}

	/*encode memory data to cms file*/
	fp = fopen( cmsPath, "w");
	if( fp == NULL){
		printf( "[%s-%d],cannot open cms file, %s\n", __FUNCTION__, __LINE__, cmsPath);
		if ((xmlPath != NULL)&&(semop(semid, &sbLeave, sizeof(sbLeave)/sizeof(struct sembuf)) == -1)) {
			printf( "%s(): semop fail\n", __FUNCTION__);
			return CMS_NOK;
		}				
		return CMS_NOK;
	}
	
	MySetFileLength(xmlShmCb->shmSize);
	ret = Encode(xmlShmCb->baseaddr, fp);
	fclose(fp);
	if ( SZ_OK !=  ret ){
		printf( "RDM encoder fail!!\n");
		return CMS_NOK;
	}	
	
	if(xmlPath != NULL){ 
		if (semop(semid, &sbLeave, sizeof(sbLeave)/sizeof(struct sembuf)) == -1) {
			printf( "%s(): semop fail\n", __FUNCTION__);
			return CMS_NOK;
		}		
	}		
	
	return CMS_OK;
}

/*
	Description: 
		use to set parameter attibute
	Parameters:
		xmlShmCb:	rdm control block
		objOff: the object offset
		parameter:	parameter name		
		flags:	attribute type
		active: active type
		#define PARAMETER_ATTR_ACTIVE	1
		#define PARAMETER_ATTR_INACTIVE	0
		any possibility that we configure attribute but no parameter?!
	return:
		return CMS_OK
	example:
	{
		*p2 = "Version"
		parameter = (uint32_t *)p2;
		flags |= PARAMETER_ATTR_WRITEABLE;
		cmsXmlSetParameterAttr(xmlShmCb, object, (char *)parameter, flags, PARAMETER_ATTR_ACTIVE);
	}
*/
int cmsXml_setParameterAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter, uint32_t flags, int active){
	cmsoffset_t metaOffset, nodeOffset, attrOffset;
	char *metaAddr, *nodeAddr;
	uint32_t attr = 0;
	uint8_t meta_len = 0;
	uint16_t meta_count;
	void *meta_ptr, *object;
	objectNode_t *node;
#ifndef SYSDEF_PARSER_ON_HOST	
	int ret = 0;
#endif

	if(parameter == NULL) {
		printf( "%s(): Error!! parameter is nil\n", __FUNCTION__);
		return CMS_NOK;
	}

	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(objOff));
	/*use object to find the meta data*/
	metaAddr = object -sizeof(cmsoffset_t);
//	memcpy(&metaOffset, metaAddr, sizeof(cmsoffset_t));
	metaOffset = *((cmsoffset_t *)(metaAddr));

	/*use oid to find the object node*/
	nodeAddr = object -sizeof(cmsoffset_t)*2;
//	memcpy(&nodeOffset, nodeAddr, sizeof(cmsoffset_t));
	nodeOffset = *((cmsoffset_t *)(nodeAddr));
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));

	meta_count = node->meta_count;
	/*get meta ptr*/
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));	
	while(meta_count){

//		memcpy(&meta_len, meta_ptr, sizeof(uint8_t));
		meta_len = *((uint8_t *)meta_ptr);
		/*compare meta name*/
		if ((meta_len != PADDING_META_LEN)&&!strcmp(parameter, (meta_ptr+sizeof(uint8_t)))){	/*find meta, change the value*/
//			memcpy(&attrOffset, (meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t))), sizeof(cmsoffset_t));
			attrOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t)))));
//			attr_ptr = cmsXmlGetObjRealAddr(xmlShmCb, attrOffset);
//			memcpy(&attr, attr_ptr, sizeof(uint32_t));
			attr = NTOHL(*((uint32_t *)(object + attrOffset)));
			if (active == PARAMETER_ATTR_ACTIVE){
#ifndef SYSDEF_PARSER_ON_HOST
				attr |= (flags & ~PARAMETER_ATTR_FIX_BITS);	/*PARAMETER_ATTR_CONFIG cannot modify*/
#else
				attr |= flags;
#endif
			}
			else{
#ifndef SYSDEF_PARSER_ON_HOST				
				attr &= ~(flags & ~PARAMETER_ATTR_FIX_BITS);
#else
				attr &= ~flags;
#endif
			}
			if (attr & PARAMETER_ATTR_CONFIG){
#ifndef SYSDEF_PARSER_ON_HOST	/*x2r default value should not mark this node to be configured!*/	
				if ((node->attributes & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
					ret = 1;
					/*if the node is index child, don't use cmsXmlCheckObjectChg() to check object change or not*/
					/*index child cannot use cmsXmlCheckObjectChg() to remove ATTR_NODECONFIGURED, index child needs to use cmsXmlSetIndexObject()*/
					/*because index child's ATTR_NODECONFIGURED not only for saving config.xml but also for checking child node occupied or not*/
				}
				else{
#if 1
					xmlShmCb->offset = objOff;
#endif
					ret = cmsXml_checkObjectChg(xmlShmCb, node);
				}
				if(ret){
					cmsXml_setNodeStatus(xmlShmCb, node, ret);
				}
#endif				
			}
			*((uint32_t *)(object + attrOffset)) = HTONL(attr);
//			memcpy((object + attrOffset), &attr, sizeof(uint32_t));
			return CMS_OK;
		}
		meta_ptr = meta_ptr + meta_len;
		meta_count--;
	}	

	return CMS_NOK;
}

static uint64_t cms64EndianTransfer(uint64_t value){
#if defined(SYSDEF_PARSER_ON_HOST) && defined(BIGENDIAN)
	uint32_t *endianPtr;
	uint32_t endian1 = 0;
	uint32_t endian2 = 0;
	uint64_t endian = 0;

	endianPtr = (uint32_t *)&value;
	memcpy(&endian1, endianPtr, sizeof(uint32_t));
	memcpy(&endian2, endianPtr + 1, sizeof(uint32_t));
	endian1 = HTONL(endian1);
	endian2 = HTONL(endian2);
	endianPtr = (uint32_t *)&endian;
	memcpy(endianPtr+1, &endian1, sizeof(uint32_t));
	memcpy(endianPtr, &endian2, sizeof(uint32_t));

	return endian;
#else
	return value;
#endif
}

/*______________________________________________________________________________
**	htoi
**
**	descriptions:
**	Convert hex-ascii to integer
**	parameters:
**	local:
**	global:
**	return:
**	called by:
**	call:
**	revision:
**____________________________________________________________________________*/
static int
htoi(
	char	*s
)
{
	int i = 0;
	char	c;

	while((c = *s++) != '\0'){
		if(c == 'x')
			continue;		/* allow 0x notation */
		if('0' <= c && c <= '9')
			i = (i * 16) + (c - '0');
		else if('a' <= c && c <= 'f')
			i = (i * 16) + (c - 'a' + 10);
		else if('A' <= c && c <= 'F')
			i = (i * 16) + (c - 'A' + 10);
		else
			goto error_ret;
			//break;
	}
	return i;
error_ret:
	return -1;
} /* htoi */

/*
	descriptions:
		Convert an Ethernet address from Hex/ASCII to binary
	parameters:
	
	return:
	
*/
static int
gether(
	uint8_t	*out,
	char	*cp
)
{
	int i,ret = 0;
	char	*pcp;

	pcp = cp;
	for(i=6; i!=0; i--)
	{
		if(i>1 && (cp = strchr(pcp,':')) == NULL)
			break;
		*cp = 0;
		ret = htoi(pcp);
		if(ret<0)
			goto error_ret;
		else
			*out++ = ret;
		pcp = cp+1;
	}
	//*out++ = htoi(pcp);
	//i--;
	return i;
error_ret:
	return -1;
}

/*set parameter needs to mark the node has been configed!*/
/*
	Description: 
		use to set parameter
	Parameters:
		xmlShmCb:	rdm control block
		objOff: the object offset
		count:	parameter number
		parameter:	pointer array of p1, v1, t1, p2, v2, t2, p3, v3, t3....
					p: parameter name pointer
					v: parameter value pointer
					t: parameter type pointer, you can use string(PARAMETER_TYPE_STRING) 
						or native type(ex. PARAMETER_TYPE_UINT8)
	return:
		return CMS_OK
	call by:
		1. DAS, direct access for change parameter value 
		2. Front-end, indirect access for change parameter value
		3. x2r, direct access for RDM initial value
	example:
		uint32_t *type_char = PARAMETER_TYPE_STRING;
		char *set[] = {"Date", "Change", (char *)&type_char};	//p1, v1, t1
		int count = 1;
		cmsXmlSetParameter(xmlShmCb, object, count, set);

*/
int cmsXml_setParameter(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, int count, char **parameter){
	cmsoffset_t metaOffset, nodeOffset, paraOffset, attrOffset;
	char *metaAddr, *nodeAddr, *meta_ptr;
	int i=0;
	objectNode_t	*node, *parent, *middle;
	uint32_t size = 0, type_size = 0, real_size = 0;
	uint8_t meta_len = 0;
	uint16_t flag=0, restore = 0;
	uint32_t type = 0;
	void *object, *sobject;
	uint32_t attr = 0;
	uint64_t tempValue;
	uint64_t maxValue;
	uint64_t minValue;
	char	*pcp;
	char *tmpStr;
	uint8_t outStr[6], *macPtr;
	int errorFlag = 0;
	//char *nodeName;
	int ret = 0, isString = 0, result = CMS_OK;
#if !defined(SYSDEF_PARSER_ON_HOST)
	char *stringAddr = NULL;
	uint32_t *stringTmp = NULL;
	char **stringDouble;
#endif
#ifdef XML_TEST_DEBUG
	int paramCount = 0;
#endif

#ifdef XML_TEST_DEBUG
	printf( "[%s-%d], Entrance.\n", __FUNCTION__, __LINE__);
#endif
	if(parameter == NULL) {
		printf( "%s(): Error!! parameter is nil\n", __FUNCTION__);
		return CMS_NOK;
	}

	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(objOff));
	while(count > 0){
		/*use object to find the meta data*/
		metaAddr = object -sizeof(cmsoffset_t);
//		memcpy(&metaOffset, metaAddr, sizeof(cmsoffset_t));
		metaOffset = *((cmsoffset_t *)metaAddr);

		/*use oid to find the object node*/
		nodeAddr = object -sizeof(cmsoffset_t)*2;
//		memcpy(&nodeOffset, nodeAddr, sizeof(cmsoffset_t));
		nodeOffset = *((cmsoffset_t *)nodeAddr);
		node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));

#ifdef XML_TEST_DEBUG
		paramCount = NTOHS(node->meta_count);
		printf("current object has %d parameters.\n", paramCount);
#endif
		/*get meta ptr*/
		meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));
		//nodeName = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->name));
		if((*(parameter+i)) != NULL && (*(parameter+i+1)) != NULL && (*(parameter+i+2))!= NULL){
			if (cmsXml_SearchParameter(xmlShmCb, node, *(parameter+i), &meta_ptr) == CMS_OK){

	//			memcpy(&meta_len, meta_ptr, sizeof(uint8_t));
				meta_len = *((uint8_t *)meta_ptr);
	//			memcpy(&type_size, (meta_ptr + meta_len - sizeof(uint32_t)), sizeof(uint32_t));
				type_size = NTOHL(*((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t))));
	//			memcpy(&paraOffset, (meta_ptr + meta_len - (sizeof(cmsoffset_t)*2+sizeof(uint32_t))), sizeof(cmsoffset_t));
				paraOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(cmsoffset_t)*2+sizeof(uint32_t)))));
				attrOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(cmsoffset_t)*1+sizeof(uint32_t)))));
	//			memcpy(&type, *(parameter+i+2), sizeof(uint32_t));
				type = *((uint32_t *)(*(parameter+i+2)));
				/*get parameter attribute*/
				attr = NTOHL(*((uint32_t *)(object+attrOffset)));
#ifndef SYSDEF_PARSER_ON_HOST					
				if ((attr & PARAMETER_ATTR_READONLY) == PARAMETER_ATTR_READONLY){
					/*if the parameter is not writeable, return i?*/
					printf( "config.xml error.\n\r");
					goto next_parameter;
				}
#endif					
				/*find offset and type of the parameter, use type to convert the parameter from string to value*/
				if(*(parameter+i+1)!=NULL)
				{
					if ((type & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
						/*merge this part with cmsXmlConvertToValue()??!!*/
						size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
						if ((type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
							type_size = PARAMETER_TYPE_STRING;			
						}
		//				else{
		//					ptr = cmsXmlConvertToValue(*(parameter+i+1), type_size);
		//				}
						isString = 1;
					}
					else if ((type & PARAMETER_RESTORE) == PARAMETER_RESTORE){ /*check is this a restore action?*/
						restore = 1;	/*mark there is a restore action and need to check NODE's ATTR_NODECONFIGURED*/						
						/*index child?*/
						if (node->attributes & ATTR_INDEXCHILD){
							size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
							parent = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->parent));
							middle = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(parent->child));
							sobject = cmsXmlGetObjRealAddr(xmlShmCb, middle->object);
							/*tmp use read only, maybe we need to add one attribute to present this parameter cannot be restored*/
							
							/*restore value*/
							memcpy((object+paraOffset), (sobject+paraOffset), size);
							/*resotre attr here*/
							memcpy((object+attrOffset), (sobject+attrOffset), sizeof(uint32_t));
							goto next_parameter;
						}
						/*check default parameter exist?*/
						if ((attr & PARAMETER_ATTR_DEFAULTVALUE) == PARAMETER_ATTR_DEFAULTVALUE){
							/*_default exist*/
							size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
							/*restore value*/
							memcpy((object+paraOffset), (object+paraOffset+size), size);							
						}
						else{
							/*_default non-exist*/
							size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
							memset((object+paraOffset), 0, size);
						}
						/*check default attribute exist?*/
						if ((attr & PARAMETER_ATTR_DEFAULTATTR) == PARAMETER_ATTR_DEFAULTATTR){
							/*default attribute exist*/
							size = sizeof(uint32_t);
							/*restore value*/
							memcpy((object+attrOffset), (object+attrOffset+size), size);							
						}
						else{
							/*default attribute non-exist*/
							size = sizeof(uint32_t);
							/*remove attibute except fix bit*/
							attr &= PARAMETER_ATTR_FIX_BITS;
							memcpy((object+attrOffset), &attr, size);
						}
							
						goto next_parameter;	/*next parameter*/
							
					}
					else{
						/*the input parameter's type is not string, type: input type, type_size: original type*/
						if (type != type_size){
							return CMS_NOK;
						}
					}					
					/*copy the value*/
					maxValue = minValue = tempValue = 0;
					switch(type_size){
						case PARAMETER_TYPE_UINT8:
						case PARAMETER_TYPE_BOOLEAN:
							/*convert to value here*/
							maxValue = *((uint8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
							minValue = *((uint8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoull(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoull(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(uint8_t *)(*(parameter+i+1));
							}
							if((uint8_t)tempValue > (uint8_t)maxValue || (uint8_t)tempValue < (uint8_t)minValue)
							{
								CMS_LOG(LL_ERROR, "uint8 The value of parameter \"%s\" is out of range(%u-%u). Value=%u\n\r",
									*(parameter+i), (uint8_t)minValue, (uint8_t)maxValue, (uint8_t)tempValue);
	        						errorFlag = 1;
								break;
							}
							if(*((uint8_t *)(object+paraOffset)) == (uint8_t)tempValue){
								result = CMS_NOCHANGE;
							}
							*((uint8_t *)(object+paraOffset)) = (uint8_t)tempValue;
//							memcpy((object+paraOffset), ptr, size);
							break;
						case PARAMETER_TYPE_UINT16:
							/*convert to value here*/
							maxValue = NTOHS(*((uint16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							minValue = NTOHS(*((uint16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoull(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoull(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(uint16_t *)(*(parameter+i+1));
							}			
				
							if((uint16_t)tempValue > (uint16_t)maxValue || (uint16_t)tempValue < (uint16_t)minValue)
							{
								CMS_LOG(LL_ERROR, "uint16 The value of parameter \"%s\" is out of range(%u-%u). Value=%u\n\r",
									*(parameter+i), (uint16_t)minValue, (uint16_t)maxValue, (uint16_t)tempValue);
        							errorFlag = 1;
								break;
							}
							if(*((uint16_t *)(object+paraOffset)) == HTONS((uint16_t)tempValue)){
								result = CMS_NOCHANGE;
							}
							*((uint16_t *)(object+paraOffset)) = HTONS((uint16_t)tempValue);
//							memcpy((object+paraOffset), &unsign16, size);
							break;
						case PARAMETER_TYPE_UINT32:
							/*convert to value here*/
							maxValue = NTOHL(*((uint32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							minValue = NTOHL(*((uint32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoull(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoull(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(uint32_t *)(*(parameter+i+1));
							}								
							if((uint32_t)tempValue > (uint32_t)maxValue || (uint32_t)tempValue < (uint32_t)minValue)
							{
								CMS_LOG(LL_ERROR, "uint32 The value of parameter \"%s\" is out of range(%u-%u). Error value=%u\n\r",
									*(parameter+i), (uint32_t)minValue, (uint32_t)maxValue, (uint32_t)tempValue);
        							errorFlag = 1;
								break;
							}
							if(*((uint32_t *)(object+paraOffset)) == HTONL((uint32_t)tempValue)){
								result = CMS_NOCHANGE;
							}								
							*((uint32_t *)(object+paraOffset)) = HTONL((uint32_t)tempValue);
//							memcpy((object+paraOffset), &unsign32, size);
							break;
						case PARAMETER_TYPE_MAC:
							/*convert to value here*/
							if (isString){
								tmpStr= *(parameter+i+1);
								{
									int len = 0;
									len=strlen(tmpStr);
									if(len!=17)
									{
										printf( "mac1 The value of parameter \"%s\" is out of range. Error value=%s, MAC value type must like XX:XX:XX:XX:XX:XX\n\r",*(parameter+i), tmpStr);
										errorFlag = 1;
										break;
									}
									pcp = *(parameter+i+1);
									ret = gether(outStr, pcp);
									if(ret > 0)
									{
										printf( "mac2 The value of parameter \"%s\" is out of range. Error value=%s, MAC value type must like XX:XX:XX:XX:XX:XX\n\r",*(parameter+i), tmpStr);
										errorFlag = 1;
										break;
									}
									else if(ret == -1)
									{
										printf( "mac3 The value of parameter \"%s\" is out of range. Error value=%s, MAC address must between 0~9,a~f or A~F.\n\r",*(parameter+i), tmpStr);
										errorFlag = 1;
										break;
									}	
								}	
								macPtr = (uint8_t *)&outStr;
							}
							else{
								macPtr = (uint8_t *)(*(parameter+i+1));
							}
							if(strcmp(object+paraOffset, (char *)macPtr) == 0){
								result = CMS_NOCHANGE;
							}	
							memcpy((object+paraOffset), macPtr, 6);
							break;
						case PARAMETER_TYPE_UINT64:
							maxValue = cms64EndianTransfer(*((uint64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							minValue = cms64EndianTransfer(*((uint64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoull(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoull(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(uint64_t *)(*(parameter+i+1));
							}									
							if((uint64_t)tempValue > (uint64_t)maxValue || (uint64_t)tempValue < (uint64_t)minValue)
							{
								CMS_LOG(LL_ERROR, "uint64 The value of parameter \"%s\" is out of range(%llu-%llu). Error value=%llu\n\r",
									*(parameter+i), (uint64_t)minValue, (uint64_t)maxValue, (uint64_t)tempValue);
        							errorFlag = 1;
								break;
							}
							if(*((uint64_t *)(object+paraOffset)) == cms64EndianTransfer((uint64_t)tempValue)){
								result = CMS_NOCHANGE;
							}
							*((uint64_t *)(object+paraOffset)) = cms64EndianTransfer((uint64_t)tempValue);
							break;
						case PARAMETER_TYPE_SINT7:
							/*convert to value here*/
							maxValue = *((int8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
							minValue = *((int8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoll(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoll(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(int8_t *)(*(parameter+i+1));
							}									
							if((int8_t)tempValue > (int8_t)maxValue || (int8_t)tempValue < (int8_t)minValue)
							{
								CMS_LOG(LL_ERROR, "sint7 The value of parameter \"%s\" is out of range(%d-%d). Error value=%d\n\r",
									*(parameter+i), (int8_t)minValue, (int8_t)maxValue, (int8_t)tempValue);
        							errorFlag = 1;
								break;
							}
							if(*((int8_t *)(object+paraOffset)) == (int8_t)tempValue){
								result = CMS_NOCHANGE;
							}
							*((int8_t *)(object+paraOffset)) = (int8_t)tempValue;
//							memcpy((object+paraOffset), ptr, size);
							break;
						case PARAMETER_TYPE_SINT15:
							/*convert to value here*/
							maxValue = NTOHS(*((int16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							minValue = NTOHS(*((int16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoll(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoll(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(int16_t *)(*(parameter+i+1));
							}									
							if((int16_t)tempValue > (int16_t)maxValue || (int16_t)tempValue < (int16_t)minValue)
							{
								CMS_LOG(LL_ERROR, "sint15 The value of parameter \"%s\" is out of range(%d-%d). Error value=%d\n\r",
									*(parameter+i), (int16_t)minValue, (int16_t)maxValue, (int16_t)tempValue);
        							errorFlag = 1;
								break;
							}
							if(*((int16_t *)(object+paraOffset)) == HTONS((int16_t)tempValue)){
								result = CMS_NOCHANGE;
							}
							*((int16_t *)(object+paraOffset)) = HTONS((int16_t)tempValue);
//							memcpy((object+paraOffset), &unsign16, size);
							break;
						case PARAMETER_TYPE_SINT31:
							/*convert to value here*/
							maxValue = NTOHL(*((int32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							minValue = NTOHL(*((int32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoll(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoll(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(int32_t *)(*(parameter+i+1));
							}									
							if((int32_t)tempValue > (int32_t)maxValue || (int32_t)tempValue < (int32_t)minValue)
							{
								CMS_LOG(LL_ERROR, "sint31 The value of parameter \"%s\" is out of range(%d-%d). Error value=%d\n\r",
									*(parameter+i), (int32_t)minValue, (int32_t)maxValue, (int32_t)tempValue);
        							errorFlag = 1;
								break;
							}
							if(*((int32_t *)(object+paraOffset)) == HTONL((int32_t)tempValue)){
								result = CMS_NOCHANGE;
							}
							*((int32_t *)(object+paraOffset)) = HTONL((int32_t)tempValue);
//							memcpy((object+paraOffset), &unsign32, size);
							break;
						case PARAMETER_TYPE_SINT63:
							maxValue = cms64EndianTransfer(*((int64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							minValue = cms64EndianTransfer(*((int64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoll(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoll(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(int64_t *)(*(parameter+i+1));
							}									
							if((int64_t)tempValue > (int64_t)maxValue || (int64_t)tempValue < (int64_t)minValue)
							{
								CMS_LOG(LL_ERROR, "sint63 The value of parameter \"%s\" is out of range(%lld-%lld). Error value=%lld\n\r",
									*(parameter+i), (int64_t)minValue, (int64_t)maxValue, (int64_t)tempValue);
        							errorFlag = 1;
								break;
							}
							if(*((int64_t *)(object+paraOffset)) == cms64EndianTransfer((int64_t)tempValue)){
								result = CMS_NOCHANGE;
							}
							*((int64_t *)(object+paraOffset)) = cms64EndianTransfer((int64_t)tempValue);
							break;
						case PARAMETER_TYPE_DATETIME:
							if(strlen(*(parameter+i+1)) > PARAMETER_TYPE_DATETIME)
							{
								CMS_LOG(LL_ERROR, "The value of parameter \"%s\" is too long. Error value=%s\n\r",*(parameter+i), *(parameter+i+1));
        							errorFlag = 1;
								break;
							}
							if(strcmp((object+paraOffset), *(parameter+i+1)) == 0){
								result = CMS_NOCHANGE;
							}								
							memcpy((object+paraOffset), *(parameter+i+1), strlen(*(parameter+i+1)));
							break;
						case PARAMETER_TYPE_STRING:
							real_size = strlen(*(parameter+i+1));
#if !defined(SYSDEF_PARSER_ON_HOST)
							if ( attr & PARAMETER_ATTR_NO_MALLOC )
							{
								stringDouble = stringTmp = ( object + paraOffset );
								if ( *stringDouble != NULL ) /* already malloc space. */
								{
									if ( strlen( *stringDouble ) > real_size ) /* new string length is smaller than old string. */
									{
										strncpy( *stringDouble, *( parameter + i + 1 ), real_size );
										*( (char *)( *stringDouble + real_size ) ) = '\0';
									}
									else if ( strncmp( *stringDouble, *( parameter + i + 1 ), real_size ) == 0 )
									{
										result = CMS_NOCHANGE;
									}
									else /* malloc new space. */
									{
										cmsXml_SetStringShmOffset( xmlShmCb, real_size + 1 );
										stringAddr = ( xmlShmCb->baseaddr + cmsXmlGetStringShmOffset( xmlShmCb ) );
										strncpy( stringAddr, *( parameter + i + 1 ), real_size );
										*( (char *)( stringAddr + real_size ) ) = '\0';
										/* write realAddr to paraOffset. */
										*stringTmp = stringAddr;
									}
								}
								else /* malloc new space. */
								{
									cmsXml_SetStringShmOffset( xmlShmCb, real_size + 1 );
									stringAddr = ( xmlShmCb->baseaddr + cmsXmlGetStringShmOffset( xmlShmCb ) );
									strncpy( stringAddr, *( parameter + i + 1 ), real_size );
									*( (char *)( stringAddr + real_size ) ) = '\0';
									/* write realAddr to paraOffset. */
									*stringTmp = stringAddr;
								}
							}
							else
#endif
							{
								if ( real_size > ( size - 1 ) ) /*size - 1 is for '\0'*/
								{
									printf( "The value of parameter \"%s\" is too long. Error value=%s\n\r", *( parameter + i ), *( parameter + i + 1 ) );
									errorFlag = 1;
									break;
								}
								if ( strcmp( ( object + paraOffset ), *( parameter + i + 1 ) ) == 0 )
								{
									result = CMS_NOCHANGE;
								}
								/*merge bug fix from Andrew at 12/26*/
								memcpy( ( object + paraOffset ), *( parameter + i + 1 ), real_size );
								*( (char *)( object + paraOffset + real_size ) ) = '\0';
							}
							break;
						default:
							printf( "%s(): Set Parameter type error!!\n", __FUNCTION__);
							break;
					}
					if(errorFlag == 1){
						return CMS_NOK;
					}
				}
				/*flag is used to mark this node is configured*/
				/*SYSDEF_PARSER_ON_HOST: if NO, means this is librdm.so*/
#ifndef SYSDEF_PARSER_ON_HOST	/*x2s default value should not mark this node to be configured!*/		
				if (attr & PARAMETER_ATTR_CONFIG){
					flag = 1;	/*this node has been configured and also need to save to config.xml*/
				}
#endif
			}
		}else{
#ifdef XML_TEST_DEBUG
			printf( "%s(%s): attention!! Name = %p, Value = %p, Type = %p.\n",__FILE__, __FUNCTION__, (*(parameter+i)), (*(parameter+i+1)), (*(parameter+i+2)));
#endif
		}
next_parameter:		
		count--;
		i += 3;
	}

	if ((flag == 1)||(restore == 1)){
		if ((node->attributes & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
			ret = 1;
			/*if the node is index child, don't use cmsXmlCheckObjectChg() to check object change or not*/
			/*index child cannot use cmsXmlCheckObjectChg() to remove ATTR_NODECONFIGURED, index child needs to use cmsXmlSetIndexObject()*/
			/*because index child's ATTR_NODECONFIGURED not only for saving config.xml but also for checking child node occupied or not*/
		}
		else{
#if 1
			xmlShmCb->offset = NTOHL( objOff );
#endif
			ret = cmsXml_checkObjectChg(xmlShmCb, node);
		}

		if (result != CMS_NOCHANGE){
			if(ret){
				cmsXml_setNodeStatus(xmlShmCb, node, ret);
			}
		}
	}

	return result;
}

